#include "ET++.ph"
#ifdef __GNUG__
#pragma implementation
#endif

#include "ObjGridView.h"

#include "Class.h"
#include "OrdColl.h"
#include "Math.h"

//---- ObjGridView -------------------------------------------------------------

NewMetaImpl(ObjGridView,GridView, (TP(coll), T(width), TB(freethis), T(cols)));

ObjGridView::ObjGridView(int id, EvtHandler *eh, int w, SeqCollection *c)
														: GridView(eh)
{
	cols= 1;
	coll= c;
	width= w;
	freethis= FALSE;
	SetId(id);
}

ObjGridView::~ObjGridView()
{
	if (freethis && coll) {
		coll->FreeAll();
		delete coll;
	}
	coll= 0;
}

Object *ObjGridView::ObjAt(const Point &cell)
{
	if (coll) {
		int ix= cell.y*cols+cell.x;
		if (ix >= 0 && ix < coll->Size())
			return coll->At(ix);
	}
	return 0;
}

Object *ObjGridView::SetObjAt(Object *op, const Point &cell)
{
    if (coll) {
	int ix= cell.y*cols+cell.x;
        if (ix >= 0 && ix < coll->Size())
	    return coll->PutAt(op, ix);
    }
    return 0;
}

void ObjGridView::SetCollection(SeqCollection *c, bool f)
{
	ClearSelection(FALSE);
	ForceRedraw();
	if (freethis && coll) {
		coll->FreeAll();
		delete coll;
	}
	coll= c;
	freethis= f;

	SetModified();
	GetMinSize();
	Scroll(cPartScrollAbs, gPoint0, TRUE);
	ForceRedraw();
}

Point ObjGridView::GetColsRows()
{
	if (coll)
		return Point(cols, (coll->Size()-1)/cols+1);
	return Point(cols, 0);
}

int ObjGridView::GetGap(Direction, int)
{
	return 0;
}

Metric ObjGridView::CellSize(const Point &cell)
{
	Object *op= ObjAt(cell);
	if (op)
		return ObjCellSize(cell, op);
	return Metric(0);
}

Metric ObjGridView::ObjCellSize(const Point &cell, Object *op)
{
	Font *f= GetCellAttributes(cell)->font;
	return Metric(Math::Max(f->Width((byte*) op->AsString()), width),
					       f->Spacing(), f->Ascender());
}

Command *ObjGridView::DoKeyCommand(int ch, Token)
{
	Point p;
	register Object *op= 0;
	int start= 0, rows= GetRows();
	Rectangle r(GetViewedRect());

	if (r.IsNotEmpty()) {
		start= r.origin.y+r.extent.y;
		if (start <= GetExtent().y) {
			Point cell;
			PosToCell(Point(0,start), &cell);
			start= cell.y;
		}
	}

	for (int i= 0; i < rows; i++) {
		p.y= (start+i) % rows;
		op= ObjAt(p);
		const u_char *sort= gStdEncoding->SortMap();
		if (op && (sort[op->AsString()[0]] == sort[ch])) {
			RevealAlign(GetCellRect(p));
			break;
		}
	}

	return gNoChanges;
}

void ObjGridView::DrawCell(const Point &cell, const Rectangle &r,
										const Rectangle &rr, bool highlight)
{
	Object *op= ObjAt(cell);
	if (GrHasColor() && highlight)
		GrPaintRect(r, gHighlightColor);
	if (op)
		DrawObjCell(cell, op, r, rr, highlight);
	if (!GrHasColor() && highlight)
		GrPaintRect(r, gHighlightColor);
}

void ObjGridView::DrawObjCell(const Point &cell, Object *op, const Rectangle &r,
														const Rectangle&, bool)
{
	CellAttributes *ca= GetCellAttributes(cell);
	Point p(r.origin);
	p.y+= ca->font->Ascender();
	GrShowString(ca->font, ca->ink, p, (byte*)op->AsString());
}

int ObjGridView::RowHeight()
{
	return gSysFont->Spacing();
}

